#ifndef COOLPOOL_SIMULATION_SIMOBJECTS_RECTANGLE_H_
#define COOLPOOL_SIMULATION_SIMOBJECTS_RECTANGLE_H_

#include <GL/freeglut.h>
#include <Plane.h>

#include "ObjectTypes.h"
#include "RectangleRenderable.h"
#include "RigidBody.h"
#include "SimObjectsExceptions.h"

using math_tools::Vector3D;

namespace coolpool
{
	// Rectangle object in 3D, it is defined by 4 points (the forth is computed), those 4 points must
	// create a valid rectangle with perpendicular sides. The computed.
	// The order of the points does not matter, the constructor is able to create it if it is possible,
	// otherwise throws NoSuchRectangle exception. The 4 points are always correctly reordered.
	// It is mostly used as floor of the map.
	// Note: It has no thickness so no edge collision can be detected.
	class Rectangle: public RigidBody
	{
	public:

		Rectangle(const Rectangle & rectangle);
		explicit Rectangle();
		Rectangle(const Vector3D & v1, const Vector3D & v2, const Vector3D & v3, const Vector3D & v4);

		virtual ~Rectangle();

		// Overrides:
		Entity * clone() const;
		const virtual BoundingCylinder & getBoundingCylinder();
		virtual IRenderable * getRenderable();
		virtual int getType() const;
		virtual bool isStatic() const;
		virtual void onUpdate(double time_step);

		// Returns the closest point on the containing plane from the given point in space.
		Vector3D closestPoint(const Vector3D & point);

		// Returns the distance of the containing plane from the given point in space.
		double distanceFrom(const Vector3D & point);

		// Returns the squared distance of containing plane from the given point in space.
		// Used for optimalization purposes.
		double distanceFromSqr(const Vector3D & point);

		// Determines whether the perpendicular projection of the point in space
		// lays whithin the rectangle.
		bool isInRec(const Vector3D & point);

		// Getters:
		inline GLuint getTexture() const
		{
			return texture_;
		}

		inline const math_tools::Plane & getPlane() const
		{
			return plane_;
		}

		// Setters:
		inline void setTexture(GLuint texture)
		{
			texture_ = texture;
		}

	private:

		// Bounding sphere of the rectangle.
		BoundingCylinder bounding_cylinder_;

		// The plane containing the rectangle.
		math_tools::Plane plane_;

		GLuint texture_;

		// 4 points of the rectangle.
		Vector3D v1_;
		Vector3D v2_;
		Vector3D v3_;
		Vector3D v4_;

		// Reorders the vertices, sets up the two sides
		// and inits the containing plan and the bounding sphere.
		void init();
	};

}

#endif
